package com.system.service;


import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import com.system.domain.APPIDConfig;
import com.system.domain.Printingparameters;
import com.system.domain.SysAppsVersionVo;
import lombok.RequiredArgsConstructor;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.*;
import java.net.ServerSocket;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 打印业务层处理
 */
@RequiredArgsConstructor
@Service
public class PrinterServiceImpl implements PrinterService {

    @Resource
    private APPIDConfig appidconfig;

    @Override
    public void printPdf(String pdfile,String printerName) throws Exception {
        File file = new File(pdfile);
        PDFprint(file, printerName);
        Path path = Paths.get(pdfile);
    }


    public static void PDFprint(File file, String printerName) throws Exception {
        PDDocument document = null;
        try {
            document = PDDocument.load(file);
            PrinterJob printJob = PrinterJob.getPrinterJob();
            printJob.setJobName(file.getName());
            if (printerName != null) {
                // 查找并设置打印机
                //获得本台电脑连接的所有打印机
                PrintService[] printServices = PrinterJob.lookupPrintServices();
                if (printServices == null || printServices.length == 0) {
                    System.out.print("打印失败，未找到可用打印机，请检查。");
                    return;
                }
                PrintService printService = null;
                //匹配指定打印机
                for (int i = 0; i < printServices.length; i++) {
                    System.out.println(printServices[i].getName());
                    if (printServices[i].getName().contains(printerName)) {
                        printService = printServices[i];
                        break;
                    }
                }
                if (printService != null) {
                    printJob.setPrintService(printService);
                } else {
                    System.out.print("打印失败，未找到名称为" + printerName + "的打印机，请检查。");
                    return;
                }
            }else {
                return;
            }
            //设置纸张及缩放
            PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.SCALE_TO_FIT);
            //设置多页打印
            Book book = new Book();
            PageFormat pageFormat = new PageFormat();
            //设置打印方向
            pageFormat.setOrientation(PageFormat.PORTRAIT);//纵向
            pageFormat.setPaper(getPaper());//设置纸张
            book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
            printJob.setPageable(book);
            printJob.setCopies(1);//设置打印份数
            //添加打印属性
            HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
            printJob.print(pars);
        } finally {
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void  generationContract(String templatePath, String outputPath, Map<String, Object> map, Printingparameters printingparameter) {
        try {
            PdfReader reader = new PdfReader(templatePath);// 读取pdf模板
            FileOutputStream out = new FileOutputStream(outputPath);
            PdfStamper stamper = new PdfStamper(reader, out);
            // 获取PDF模板文件中的表单域
            AcroFields form = stamper.getAcroFields();
            Map<String, AcroFields.Item> fieldMap = form.getFields();
            StringBuilder Text1 = new StringBuilder();
            StringBuilder Text2 = new StringBuilder();
//            Text2.append(printingparameter.getDeviceQr()==null?"":printingparameter.getDeviceQr()+("\n"));
            Text2.append(printingparameter.getDetype()==null?"":printingparameter.getDetype()+("\n"));
            Text2.append(printingparameter.getDeviceBrand()==null?"":printingparameter.getDeviceBrand()+("\n"));
            Text2.append(printingparameter.getDeviceModel()==null?"":printingparameter.getDeviceModel()+("\n"));

//            Text2.append(printingparameter.getDeviceStatus()==null?"":printingparameter.getDeviceStatus());

            Text2.append(map.get("device_condition")==null? "" : map.get("device_condition").toString()).append("\n");
            Text1.append(printingparameter.getPropertiesValue()==null?"":printingparameter.getPropertiesValue());
            Text1.append(printingparameter.getDeviceDetailAttachment()==null?"":printingparameter.getDeviceDetailAttachment());
            Text1.append(printingparameter.getDeviceFault()==null?"":printingparameter.getDeviceFault());
            //目前先用打印机pc端的时间
            // 使用 LocalDate 只处理日期部分
            LocalDate currentDate = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d");
            String formattedDate = currentDate.format(formatter);


            Text1.append(map.get("remark")==null? "" : map.get("remark").toString()).append("\n");
            map.put("Text1",Text1);
            map.put("Text2",Text2);
            map.put("deviceQr",printingparameter.getDeviceQr());
            map.put("Text3",formattedDate);
            //遍历表单域，给表单域赋值
            for (Map.Entry<String, AcroFields.Item> entry : fieldMap.entrySet()) {
                String name = entry.getKey();
                form.setField(name, map.get(name).toString());
            }

            //如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.setFormFlattening(true);
            stamper.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public static String executeCommand(String command) throws IOException {
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        StringBuilder output = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            if (!line.isEmpty()) {
                output.append(line).append("\n");
            }
        }
        reader.close();
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 去除第一行标题信息
        String[] lines = output.toString().split("\n");
        if (lines.length > 1) {
            return lines[1].trim();
        }
        return "";
    }

    public static Paper getPaper() {
        Paper paper = new Paper();

        // 将毫米转换为1/72英寸
        double mmTo72thsInch = 72 / 25.4;

        // 设置纸张大小，50mm * 30mm
        double widthIn72nds = 50 * mmTo72thsInch;
        double heightIn72nds = 30 * mmTo72thsInch;
        paper.setSize(widthIn72nds, heightIn72nds);

        // 设置边距，单位是1/72英寸
        double marginLeftIn72nds = 1.52 * mmTo72thsInch;
        double marginTopIn72nds = 2.96 * mmTo72thsInch;

        // 设置图像区域，注意要减去左右和上下边距（这里需要转换为int，因为setImageableArea方法通常接受int参数）
        int imageableWidth = (int) (widthIn72nds - (marginLeftIn72nds + marginLeftIn72nds));
        int imageableHeight = (int) (heightIn72nds - (marginTopIn72nds + marginTopIn72nds));
        paper.setImageableArea(0, 0, imageableWidth, imageableHeight); // 注意：这里的0,0是图像区域的左上角相对于纸张左上角的偏移量，如果需要设置非零偏移量，请相应调整

        // 注意：上面的setImageableArea调用假设图像区域从纸张的左上角开始。如果您的打印库要求从纸张的物理边缘开始计算边距，并且纸张有不可打印区域，您可能需要调整这些值。

        return paper;

    }

    @Override
    public Boolean getInfoBySN(String serverSn) {

//        String url = "http://localhost:8888/system/printerServer/allowed/" + serverSn;
//        String url = "http://139.196.241.152:8888/system/printerServer/allowed/"+serverSn;//正式服
//        String url = "http://121.5.163.108:8888/system/printerServer/allowed/"+serverSn;//测试服
        String url = appidconfig.getUrl()+"/system/printerServer/allowed/" +serverSn;
        // 创建 RestTemplate
        RestTemplate restTemplate = new RestTemplate();

        // 发送 GET 请求
        ResponseEntity<Boolean> response = restTemplate.exchange(url, HttpMethod.GET, null, Boolean.class);

        // 获取返回的 Boolean 值
        return Boolean.TRUE.equals(response.getBody());
    }

    @Override
    public void downloadJar(SysAppsVersionVo sysAppsVersionVo) throws IOException, InterruptedException {
        // 创建 URL 对象
        URL url = new URL(sysAppsVersionVo.getInstallPackageUrl());

        String versionNumber = sysAppsVersionVo.getVersionNumber();
        String desktopPath = System.getProperty("user.home") + File.separator + "Desktop";
        // 拼接保存的文件名，这里假设文件名为 downloaded.jar
        // 拼接 printer_part 文件夹路径
        String printerPartPath = desktopPath + File.separator + "printer_part";

        // 创建 printer_part 文件夹，如果不存在的话
        File printerPartDir = new File(printerPartPath);
        if (!printerPartDir.exists()) {
            printerPartDir.mkdirs();
        }

        String savePath = printerPartPath + File.separator +"Printer_"+versionNumber+".jar";

        // 打开连接并获取输入流
        try (InputStream in = url.openStream();
             // 创建一个可读的字节通道
             ReadableByteChannel rbc = Channels.newChannel(in);
             // 创建文件输出流，用于将数据写入本地文件
             FileOutputStream fos = new FileOutputStream(savePath)) {
            // 将通道中的数据传输到文件输出流
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        }catch (Exception e){
            e.printStackTrace();
            return;
        }
        System.out.println("第一版本:JAR 包下载完成，保存路径: " + savePath);
        long pid = ProcessHandle.current().pid();
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        // 定义要延迟执行的任务
        Runnable task = () -> {
            try {
                // 构建 taskkill 命令
                ProcessBuilder killProcessBuilder = new ProcessBuilder("taskkill", "/F", "/PID", String.valueOf(pid));
                Process killProcess = killProcessBuilder.start();
                // 等待终止进程命令执行完成
                int killExitCode = killProcess.waitFor();
                if (killExitCode == 0) {
                    System.out.println("JAR 包已停止");
                } else {
                    System.out.println("停止当前 JAR 包时出现错误，退出码: " + killExitCode);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        };
        // 安排任务在两分钟（120 秒）后执行
        executor.schedule(task, 10, TimeUnit.SECONDS);
        // 可以在这里添加主线程的其他逻辑
        // 关闭执行器
        executor.shutdown();

        String newport = "";
        // 使用 split 方法按 . 分割字符串
        int lastIndex = versionNumber.lastIndexOf('.');
        if (lastIndex != -1) {
            // 截取最后一个 . 后面的部分
            String result = versionNumber.substring(lastIndex + 1);
            newport="808"+result;
            System.out.println(result);
        }

// 要指定的端口号
// 构建命令列表，调整参数顺序确保JVM参数在-jar之前
        List<String> command = new ArrayList<>();
        command.add("java");
        command.add("-jar");
        command.add("-Dfile.encoding=utf-8");
        command.add(savePath); // 确保savePath被正确引用（如有空格）
        command.add("--server.port=" + newport);

// 构建启动新CMD窗口的命令列表，避免拼接字符串
        List<String> cmdCommand = new ArrayList<>();
        cmdCommand.add("cmd");
        cmdCommand.add("/c");
        cmdCommand.add("start");
        cmdCommand.add("\"" +"打印机"+ sysAppsVersionVo.getVersionNumber() + "\"");
        cmdCommand.addAll(command); // 直接添加命令参数

        try {
            ProcessBuilder processBuilder = new ProcessBuilder(cmdCommand);
            // 可选：设置工作目录，如 processBuilder.directory(new File("工作目录路径"));
            processBuilder.start();
        } catch  (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationContract02(String templatePath, String outputPath, Map<String, Object> map, Printingparameters printingparameter) {
        try {
            PdfReader reader = new PdfReader(templatePath);// 读取pdf模板
            FileOutputStream out = new FileOutputStream(outputPath);
            PdfStamper stamper = new PdfStamper(reader, out);
            // 获取PDF模板文件中的表单域
            AcroFields form = stamper.getAcroFields();
            Map<String, AcroFields.Item> fieldMap = form.getFields();
            StringBuilder Text1 = new StringBuilder();
            StringBuilder Text2 = new StringBuilder();
            Text2.append(printingparameter.getDeviceDetailAttachment()==null?"":printingparameter.getDeviceDetailAttachment());
            Text1.append(printingparameter.getDeviceFault()==null?"":printingparameter.getDeviceFault());
            map.put("Text1",Text1);
            map.put("Text2",Text2);
            map.put("deviceQr",printingparameter.getDeviceQr());
            //遍历表单域，给表单域赋值
            for (Map.Entry<String, AcroFields.Item> entry : fieldMap.entrySet()) {
                String name = entry.getKey();
                form.setField(name, map.get(name).toString());
            }
            stamper.setFormFlattening(true);
            stamper.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



